#include "mainwindow.h"
#include "hiscoresdialog.h"
#include "blockitem.h"

int ekran_gen = 640;
int ekran_uzun = 360;

bool CHEAT = false;
bool ball_keeper = false;

int bat_gen = 64;
int bat_uzun = 16;

int top_gen = 16;
int top_uzun = 16;

int top_bas_hiz_x = 4;
int top_bas_hiz_y = 6;
int max_top_hiz_x = 10;
int mermi_hiz = 8;
int bat_hiz_x = 13;

int max_hiscore_sayisi = 10;

int bat_hand_uzun = 6;
int bat_hand_gen = 3;

OptionsGamestate::OptionsGamestate(MainWindow *mainWindow) :
        Gamestate(mainWindow) {

}

OptionsGamestate::~OptionsGamestate() {

}

void OptionsGamestate::clickedStart()
{
    Gamestate *gamestate = new PlayingGamestate(mainWindow);
    mainWindow->setGamestate(gamestate);
}

void OptionsGamestate::clickedHiscores()
{
    HiscoresDialog hiscoresDialog(mainWindow);
    hiscoresDialog.showMaximized();
    hiscoresDialog.exec();
}

void OptionsGamestate::clickedAbout() {
    QString text = tr("QTronce is an easy breakout game.\nAuthors: \nYusuf Amir TEZCAN\nOmer Faruk Oruc\nMuharrem SEKEROGLU");
    QMessageBox::about(mainWindow, tr("About QTronce"), text);
}

void OptionsGamestate::clickedExit()
{
    qApp->exit();
}

void OptionsGamestate::start() {
    QWidget *centralWidget = new QWidget(mainWindow);
    this->mainWindow->setCentralWidget(centralWidget);

    QVBoxLayout *layout = new QVBoxLayout();
    centralWidget->setLayout(layout);

    QLabel *titleLabel = new QLabel(tr("QTronce"));
    titleLabel->setAlignment(Qt::AlignCenter);
    layout->addWidget(titleLabel);

    QPushButton *startButton = new QPushButton(tr("Start a new game"));
    layout->addWidget(startButton);
    connect(startButton, SIGNAL(clicked()), this, SLOT(clickedStart()));

    QPushButton *hiscoresButton = new QPushButton(tr("Hi-Scores"));
    layout->addWidget(hiscoresButton);
    connect(hiscoresButton, SIGNAL(clicked()), this, SLOT(clickedHiscores()));

    QPushButton *aboutButton = new QPushButton(tr("About"));
    layout->addWidget(aboutButton);
    connect(aboutButton, SIGNAL(clicked()), this, SLOT(clickedAbout()));

    QPushButton *exitButton = new QPushButton(tr("Exit"));
    layout->addWidget(exitButton);
    connect(exitButton, SIGNAL(clicked()), this, SLOT(clickedExit()));
}

void OptionsGamestate::stop()
{
    delete mainWindow->centralWidget();
    mainWindow->setCentralWidget(NULL);
}

void OptionsGamestate::registerScore(int score, int level) {
    if(score <= 0)
        return;
    if(mainWindow->getHiscores().size() > max_hiscore_sayisi)
    {
        Hiscore lastHiscore = mainWindow->getHiscores().at(max_hiscore_sayisi-1);
        if( score < lastHiscore.getScore() || ( score == lastHiscore.getScore() && level <= lastHiscore.getLevel() ) )
        {
            return;
        }
    }
    QDialog *enterHiscoreWindow = new QDialog(mainWindow);
    QVBoxLayout *layout = new QVBoxLayout();
    enterHiscoreWindow->setLayout(layout);

    QLineEdit *nameEdit = NULL;

    QString text = "You scored " + QString::number(score) + "!  Enter your name:";
    QLabel *scoreLabel = new QLabel(text);
    layout->addWidget(scoreLabel);

    nameEdit = new QLineEdit("");
    layout->addWidget(nameEdit);

    layout->addStretch();

    QPushButton *okButton = new QPushButton("OK");
    layout->addWidget(okButton);
    connect(okButton, SIGNAL(clicked()), enterHiscoreWindow, SLOT(accept()));

    enterHiscoreWindow->showFullScreen();
    enterHiscoreWindow->exec();

    QString name = nameEdit->text();
    Hiscore hiscore(name, score, level);
    this->mainWindow->addHiscore(hiscore);

    delete enterHiscoreWindow;
}

PlayingGamestate::PlayingGamestate(MainWindow *mainWindow) :
        Gamestate(mainWindow),
        gameTime(0),
        scene(NULL), view(NULL),
        paused(false),
        itemBat(NULL), itemBall(NULL),
        itemScore(NULL), itemLives(NULL), itemLevel(NULL),
        itemPause(NULL), itemQuit(NULL),

        ball_sp_x(0), ball_sp_y(0),
        bat_has_target(false), bat_target_x(0),
        score(0), lives(3), level(1),
        level_complete(false),
        has_message(false), message_pauses(false), message_start_time(0), itemMessage(NULL),
        bonus_fireball(false), bonus_fireball_start_time(0), bonus_bullets(false), bonus_bullets_start_time(0), bullets_fire_start_time(0)
{
}

PlayingGamestate::~PlayingGamestate() {

}

void PlayingGamestate::start() {
    scene = new QGraphicsScene(mainWindow);
    scene->setSceneRect(0, 0, ekran_gen, ekran_uzun);

    view = new QGraphicsView(scene, mainWindow);
    view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    view->setFrameStyle(QFrame::NoFrame);
    view->setFocusPolicy(Qt::NoFocus);

    QPixmap backgroundPixmap(ekran_gen, ekran_uzun);
    backgroundPixmap.fill(Qt::black);
    QPainter backgroundPainter(&backgroundPixmap);
    backgroundPainter.setPen(QPen(Qt::NoPen));
    const int n_stars_c = 128;
    for(int i=0;i<n_stars_c;i++) {
        int xpos = rand() % ekran_gen;
        int ypos = rand() % ekran_uzun;
        int bright = rand() % 256;

        const int point_w_c = 2;
        QRadialGradient pointGrad(QPointF(0, 0), point_w_c);
        pointGrad.setColorAt(0, QColor(bright, bright, bright));
        pointGrad.setColorAt(1, QColor(bright, bright, 0));
        backgroundPainter.setBrush(QBrush(pointGrad));
        backgroundPainter.drawRect(xpos, ypos, point_w_c, point_w_c);
    }
    scene->setBackgroundBrush(QBrush(backgroundPixmap));

    view->setCacheMode(QGraphicsView::CacheBackground);

    mainWindow->setCentralWidget(view);

    view->showFullScreen();

    this->resizeEvent(NULL);

    scene->addRect(0, 0, scene->width()-1, scene->height()-1, QPen(Qt::white));
    itemBall = scene->addEllipse(0, 0, top_gen, top_uzun, QPen(Qt::NoPen), QBrush(Qt::red));

    bat_hand1 = scene->addRect( 0, 0, bat_hand_gen, bat_hand_uzun, QPen(Qt::NoPen), QBrush(QColor(Qt::white)));
    bat_hand2 = scene->addRect( 0, 0, bat_hand_gen, bat_hand_uzun, QPen(Qt::NoPen), QBrush(QColor(Qt::white)));

    setBallColor();

    QLinearGradient linearGradBat(0, 0, 0, bat_uzun);
    linearGradBat.setColorAt(0, Qt::white);
    linearGradBat.setColorAt(1, Qt::gray);

    itemBat = scene->addRect(0, 0, bat_gen, bat_uzun, QPen(Qt::NoPen), QBrush(linearGradBat));
    initBallAndBat(false);
    initLevel();

    itemScore = scene->addText("");
    itemScore->setZValue(1.0);
    QFont font = itemScore->font();
    font.setPointSize(8);

    itemScore->setFont(font);
    itemScore->setPos(16, 16);
    itemScore->setDefaultTextColor(Qt::yellow);
    this->changeScore(0);

    itemLives = scene->addText("");
    itemLives->setZValue(1.0);
    itemLives->setFont(font);
    itemLives->setPos(176, 16);
    itemLives->setDefaultTextColor(Qt::yellow);
    this->changeLives(0);

    itemLevel = scene->addText("");
    itemLevel->setZValue(1.0);
    itemLevel->setFont(font);
    itemLevel->setPos(296, 16);
    itemLevel->setDefaultTextColor(Qt::yellow);
    this->changeLevel(0);

    itemQuit = scene->addText("QUIT");
    itemQuit->setZValue(1.0);
    itemQuit->setFont(font);
    itemQuit->setPos(16, 64);
    itemQuit->setDefaultTextColor(Qt::white);

    itemPause = scene->addText("PAUSE");
    itemPause->setZValue(1.0);
    itemPause->setFont(font);
    itemPause->setPos(16, 112);
    itemPause->setDefaultTextColor(Qt::white);
}

void PlayingGamestate::stop() {
    delete scene;
    scene = NULL;
    delete mainWindow->centralWidget();
    view = NULL;
    mainWindow->setCentralWidget(NULL);
}

void PlayingGamestate::setBallColor() {
    QRadialGradient radialGrad(QPointF(0, 0), top_gen);
    radialGrad.setColorAt(0, Qt::blue);
    if( this->bonus_fireball ){
        radialGrad.setColorAt(0.5 , QColor(Qt::yellow));
        radialGrad.setColorAt(1, QColor(255,127,0));
    } else{
        radialGrad.setColorAt(0.5, Qt::red);
        radialGrad.setColorAt(1.0, Qt::yellow);
    }
    itemBall->setBrush(radialGrad);
 }

void PlayingGamestate::initBallAndBat(bool lost_life) {
    itemBall->setPos((ekran_gen - top_gen)/2, 225);
    ball_sp_x = top_bas_hiz_x;
    if(rand() % 2 == 1)
        ball_sp_x = -top_bas_hiz_x;
    ball_sp_y = top_bas_hiz_y;

    itemBat->setPos((ekran_gen - bat_gen) / 2, ekran_uzun - 2 * bat_uzun);
    bat_has_target = false;

    bat_hand1->setPos((itemBat->pos().x()), (itemBat->pos().y() - bat_hand_uzun));
    bat_hand2->setPos((itemBat->pos().x()-3 + (bat_gen)), (itemBat->pos().y() - bat_hand_uzun));

    if( lives == 1 && lost_life )
        this->setMessage("Last Ball!", true);
    else
        this->setMessage("Get Ready!", true);
}

const int n_blocks_x = 8;
const int n_blocks_y = 6;
const int x_kenar = (ekran_gen - n_blocks_x * block_gen) / 2;
const int y_kenar = block_uzun;

int PlayingGamestate::indexHash(qreal x, qreal y) {
    int n_x = (x - x_kenar) / block_gen;
    int n_y = (y - y_kenar) / block_uzun;

    int index = n_y * n_blocks_x + n_x;
    return index;
}

BlockItem *PlayingGamestate::blockAt(qreal x, qreal y) {
    if( x < x_kenar || x >= x_kenar + n_blocks_x * block_gen )
        return NULL;
    if( y < y_kenar || y >= y_kenar + n_blocks_y * block_uzun )
        return NULL;
    int index = indexHash(x, y);
    BlockItem *blockItem = blocksHashMap[index];
    return blockItem;
}

void PlayingGamestate::initLevel() {
    this->bonus_fireball = false;
    this->bonus_bullets = false;
    ball_keeper = false;
    setBallColor();

    foreach (QGraphicsItem *block, blocks) {
        delete block;
    }
    blocks.clear();
    blocksHashMap.clear();

    //yeni bölümü yükle
    QString levelData = "";
    const int max_levels_c = 12;
    int mlevel = (level-1) % max_levels_c;
//switch
    if( mlevel == 0 ) {
        levelData += "bbbbbbbb";
        levelData += "rrrpgrrr";
        levelData += "rrrrrrrr";
        levelData += "   w    ";
        levelData += "        ";
        levelData += "        ";
    }
    else if( mlevel == 1 ) {
        levelData += " b bb b ";
        levelData += "bbbbbbbb";
        levelData += "rorrrrwr";
        levelData += "rrrrrrrr";
        levelData += "        ";
        levelData += "        ";
    }
    else if( mlevel == 2 ) {
        levelData += " w bb g ";
        levelData += "   bb   ";
        levelData += "rrrbbrrr";
        levelData += "rrrbbrrr";
        levelData += "   bb   ";
        levelData += " p    p ";
    }
    else if( mlevel == 3 ) {
        levelData += "        ";
        levelData += "bbbbbbbb";
        levelData += "rrrpgrrr";
        levelData += "orrrrrro";
        levelData += "xxxxxxxx";
        levelData += "        ";
    }
    else if( mlevel == 4 ) {
        levelData += "bbbbbbbb";
        levelData += "rrrrrrrr";
        levelData += " w   o  ";
        levelData += " p   p  ";
        levelData += "rrrrrrrr";
        levelData += "bbbbbbbb";
    }
    else if( mlevel == 5 ) {
        levelData += "b      b";
        levelData += "b  xx  b";
        levelData += "b  gp  b";
        levelData += "bb rr bb";
        levelData += " b    b ";
        levelData += " bbprbb ";
    }
    else if( mlevel == 6 ) {
        levelData += " b   bb ";
        levelData += " xx  xx ";
        levelData += "    r   ";
        levelData += "    x  r";
        levelData += " r     x";
        levelData += " x      ";
    }
    else if( mlevel == 7 ) {
        levelData += " b b b b";
        levelData += "b brbrb ";
        levelData += " brbobrb";
        levelData += "b brbrb ";
        levelData += " b b b b";
        levelData += "b b b b ";
    }
    else if( mlevel == 8 ) {
        levelData += "prbrbrbg";
        levelData += "brbrbrbr";
        levelData += "brbrbrbr";
        levelData += "brbrbrbr";
        levelData += "wrbrbrbo";
        levelData += "xrxrxrxr";
    }
    else if( mlevel == 9 ) {
        levelData += " p    p ";
        levelData += " r pp r ";
        levelData += " w pp w ";
        levelData += " r pp r ";
        levelData += " w pp w ";
        levelData += " p    p ";
    }
    else if( mlevel == 10 ) {
        levelData += "rorororo";
        levelData += "orororor";
        levelData += "pppppppp";
        levelData += "bbbbbbbb";
        levelData += "rrrrrrrr";
        levelData += "xxxxxxxx";
    }
    else if( mlevel == 11 ) {
        levelData += "xrrrxorr";
        levelData += "xrxbxbxr";
        levelData += "xrxoxbxr";
        levelData += "xrxgxbxr";
        levelData += "xpxbbbxr";
        levelData += "xoxxxxxr";
    }

    QLinearGradient linearGradRed(0, 0, block_gen, block_uzun);
    linearGradRed.setColorAt(0, Qt::red);
    linearGradRed.setColorAt(1, Qt::darkRed);
    QLinearGradient linearGradBlue(0, 0, block_gen, block_uzun);
    linearGradBlue.setColorAt(0, Qt::blue);
    linearGradBlue.setColorAt(1, Qt::darkBlue);
    QLinearGradient linearGradGreen(0, 0, block_gen, block_uzun);
    linearGradGreen.setColorAt(0, Qt::green);
    linearGradGreen.setColorAt(1, Qt::darkGreen);
    QLinearGradient linearGradPurple(0, 0, block_gen, block_uzun);
    linearGradPurple.setColorAt(0, QColor(255, 0, 255));
    linearGradPurple.setColorAt(1, QColor(127, 0, 127));
    QLinearGradient linearGradOrange(0, 0, block_gen, block_uzun);
    linearGradOrange.setColorAt(0, QColor(255, 165, 0));
    linearGradOrange.setColorAt(1, QColor(127, 82, 0));
    QLinearGradient linearGradBrown(0, 0, block_gen, block_uzun);
    linearGradBrown.setColorAt(0, QColor(150, 75, 0));
    linearGradBrown.setColorAt(1, QColor(75, 37, 0));
    QLinearGradient linearGradYellow(0, 0, block_gen, block_uzun);
    linearGradYellow.setColorAt(0, Qt::yellow);
    linearGradYellow.setColorAt(1, Qt::darkYellow);
    QLinearGradient linearGradWhite(0, 0, block_gen, block_uzun);
    linearGradWhite.setColorAt(0, Qt::white);
    linearGradWhite.setColorAt(1, Qt::gray);
    QLinearGradient linearGradBlonde(0, 0, block_gen, block_uzun);
    linearGradBlonde.setColorAt(0, QColor(184, 138, 0));
    linearGradBlonde.setColorAt(1, QColor(205, 138, 0));

    for(int y = 0 , c = 0 ; y < n_blocks_y ; y++)
    {
        int ypos = y_kenar + y * block_uzun;

        for(int x = 0 ; x < n_blocks_x ; x++ , c++)
        {
            QChar ch = levelData.at(c);
            if( ch == ' ' ) {
                //geç
            }
            else {
                int xpos = x_kenar + x * block_gen;
                BlockItem *itemBlock = NULL;
                if( ch == 'r' ) {
                    itemBlock = new BlockItem(QBrush(linearGradRed));
                }
                else if( ch == 'b' ) {
                    itemBlock = new BlockItem(QBrush(linearGradBlue));
                    itemBlock->setScore(10);
                }
                else if( ch == 'g' ) {
                    itemBlock = new BlockItem(QBrush(linearGradGreen));
                    itemBlock->setScore(0);
                    itemBlock->setBlockType(BlockItem::BLOCKTYPE_EXTRALIFE);
                }
                else if( ch == 'p' ) {
                    itemBlock = new BlockItem(QBrush(linearGradPurple));
                    itemBlock->setScore(20);
                    itemBlock->setBlockType(BlockItem::BLOCKTYPE_FASTBALL);
                }
                else if( ch == 'o' ) {
                    itemBlock = new BlockItem(QBrush(linearGradOrange));
                    itemBlock->setScore(0);
                    itemBlock->setBlockType(BlockItem::BLOCKTYPE_FIREBALL);
                }
                else if( ch == 'x' ) {
                    itemBlock = new BlockItem(QBrush(linearGradBrown));
                    itemBlock->setScore(0);
                    itemBlock->setBlockType(BlockItem::BLOCKTYPE_BRICK);
                }
                else if( ch == 'y' ) {
                    itemBlock = new BlockItem(QBrush(linearGradYellow));
                    itemBlock->setScore(100);
                    itemBlock->setBlockType(BlockItem::BLOCKTYPE_EXPLOSION);
                }
                else if( ch == 'w' ) {
                    itemBlock = new BlockItem(QBrush(linearGradWhite));
                    itemBlock->setScore(100);
                    itemBlock->setBlockType(BlockItem::BLOCKTYPE_BULLETS);
                }
                else if ( ch ==  'k' ) {
                    itemBlock = new BlockItem(QBrush(linearGradBlonde));
                    itemBlock->setScore(0);
                    itemBlock->setBlockType(BlockItem::BLOCKTYPE_KEEPER);
                }

                itemBlock->setPos(xpos, ypos);
                scene->addItem(itemBlock);
                blocks.push_back(itemBlock);

                blocksHashMap.insert(this->indexHash(xpos, ypos), itemBlock);
            }
        }
    }
}

void PlayingGamestate::updateScene() {
    if( paused ) {
        return;
    }

    gameTime += time_per_frame_c;

    if(this->has_message){
        if( gameTime - message_start_time > 1500){
            delete itemMessage;
            this->has_message = false;
            if(lives <= 0){
                OptionsGamestate *gamestate = new OptionsGamestate(mainWindow);
                mainWindow->setGamestate(gamestate);
                gamestate->registerScore(this->score, this->level);
            }
            else if (level_complete) {
                level_complete = false;
                this->changeLives(1);
                this->initLevel();
                this->changeLevel(1);
                this->initBallAndBat(false);
                this->changeScore(100);
            }
        }
        if( message_pauses ){
            return;
        }
    }

    const int bonus_time_c = 10000;

    if(this->bonus_fireball & gameTime - bonus_fireball_start_time > bonus_time_c) {
        this->bonus_fireball = false;
        setBallColor();
    }
    if( this->bonus_bullets && gameTime - this->bonus_bullets_start_time > bonus_time_c ) {
        this->bonus_bullets = false;
    }

    //Move Ball ;D
    itemBall->moveBy(ball_sp_x, ball_sp_y);

    //ekran sınırlarıyla çarpışma
    QPointF pos = itemBall->pos();
    if( pos.x() + top_gen >= scene->width() ) {
        itemBall->setPos(scene->width()-1-top_gen, pos.y());
        ball_sp_x = - ball_sp_x;
    }
    else if( pos.x() < 0 ) {
        itemBall->setPos(0, pos.y());
        ball_sp_x = - ball_sp_x;
    }
    if( pos.y() < 0 ) {
        itemBall->setPos(pos.x(), 0);
        ball_sp_y = - ball_sp_y;
    }
    pos = itemBall->pos();

        // lose life
    if( pos.y() + top_uzun >= scene->height() ) {

        if(CHEAT)
        {
            itemBall->setPos(pos.x(), scene->height()-1-top_uzun);
            ball_sp_y = - ball_sp_y;
        }
        else
        {
            this->changeLives(-1);
            if( lives > 0 ) {
                this->initBallAndBat(true);
            }
            else {
                this->setMessage("Game Over!", true);
            }
        }
    }

    if( ball_sp_y > 0 && (pos.y() + top_uzun >= itemBat->pos().y()) &&
        (pos.y() + top_uzun <= itemBat->pos().y() + bat_uzun) ) {

        if( pos.x() + top_gen >= itemBat->pos().x() && pos.x() <= itemBat->pos().x() + bat_gen ) {
            qDebug("top bat'a vurdu");
            ball_sp_y = - ball_sp_y;
            const float bat_kenar_f = 0.3f;
            if( pos.x() + top_gen/2 <= itemBat->pos().x() + bat_kenar_f*bat_gen ) {
                // sola vuruş
                qDebug("sola vurdu");
                ball_sp_x = ball_sp_x - 2;
            }
            else if( pos.x() + top_gen/2 >= itemBat->pos().x() + (1.0f-bat_kenar_f) * bat_gen ) {
                // sağa vuruş
                qDebug("sağa vurdu");
                ball_sp_x = ball_sp_x + 2;
            }
            ball_sp_x = qMin(ball_sp_x, max_top_hiz_x);
            ball_sp_x = qMax(ball_sp_x, -max_top_hiz_x);
            if( ball_sp_x == 0 ) {
                // sıfır vektörüyle sağa sola gitmesini önler ;D(M.Ş)
                ball_sp_x = ((rand() % 2) == 0) ? -1 : 1;
            }
            itemBall->setPos(pos.x(), itemBat->pos().y() - bat_uzun);
            pos = itemBall->pos();
        }
    }

    bool deleted_any_blocks = false;

    //bricklerle çarpışma
    QList<QGraphicsItem *> collideBall = scene->collidingItems(itemBall);
    if(collideBall.size() > 0)
    {
        QPointF topPos = itemBall->pos() + QPointF(top_gen/2, 0);
        QPointF bottomPos = itemBall->pos() + QPointF(top_gen/2, top_uzun);
        QPointF leftPos = itemBall->pos() + QPointF(0, top_uzun/2);
        QPointF rightPos = itemBall->pos() + QPointF(top_gen, top_uzun/2);
        QPointF topleftPos = itemBall->pos();
        QPointF toprightPos = itemBall->pos() + QPointF(top_gen, 0);
        QPointF bottomleftPos = itemBall->pos() + QPointF(0, top_uzun);
        QPointF bottomrightPos = itemBall->pos() + QPointF(top_gen, top_uzun);
        foreach(QGraphicsItem *item, collideBall) {
            if( item->type() == CUSTOMITEMTYPE_BLOCK ) {

                BlockItem *blockItem = static_cast<BlockItem *>(item);
                bool hit = false;
                if( !this->bonus_fireball || blockItem->getBlockType() == BlockItem::BLOCKTYPE_BRICK ) {
                    bool hitsTop = item->contains(item->mapFromScene(topPos));
                    if( hitsTop ) {
                        hit = true;
                        if( ball_sp_y < 0 )
                            ball_sp_y = - ball_sp_y;
                    }
                    bool hitsBottom = item->contains(item->mapFromScene(bottomPos));
                    if( hitsBottom ) {
                        hit = true;
                        if( ball_sp_y > 0 )
                            ball_sp_y = - ball_sp_y;
                    }
                    bool hitsLeft = item->contains(item->mapFromScene(leftPos));
                    if( hitsLeft ) {
                        hit = true;
                        if( ball_sp_x < 0 )
                            ball_sp_x = - ball_sp_x;
                    }
                    bool hitsRight = item->contains(item->mapFromScene(rightPos));
                    if( hitsRight ) {
                        hit = true;
                        if( ball_sp_x > 0 )
                            ball_sp_x = - ball_sp_x;
                    }
                }
                else {
                    hit = true;
                }
                if( hit ) {

                    if( hitBlock(blockItem) ) {
                        deleted_any_blocks = true;
                    }
                }
            }
        }
    }

    // mermi ilerlet
    const int bullet_size_c = 8;
    QList<QGraphicsItem *> killList;
    foreach(QGraphicsItem *bullet, bullets) {
        bullet->moveBy(0, -mermi_hiz);
        bool kill_bullet = false;
        if( bullet->pos().y() + bullet_size_c < 0 ) {
            kill_bullet = true;
        }
        else {
            BlockItem *blockItem = this->blockAt(bullet->pos().x(), bullet->pos().y());
            if( blockItem != NULL ) {
                kill_bullet = true;
                if( hitBlock(blockItem) ) {
                    deleted_any_blocks = true;
                }
            }
            else {
                blockItem = this->blockAt(bullet->pos().x() + bullet_size_c - 1, bullet->pos().y());
                if( blockItem != NULL ) {
                    kill_bullet = true;
                    if( hitBlock(blockItem) ) {
                        deleted_any_blocks = true;
                    }
                }
            }
        }
        if( kill_bullet ) {
            killList.push_back(bullet);
        }
    }
    foreach(QGraphicsItem *bullet, killList) {
        bullets.removeOne(bullet);
        delete bullet;
    }

    if( this->bonus_bullets ) {
        if( gameTime - this->bullets_fire_start_time >= 500 ) {
            // fire new bullet
            QRadialGradient radialGrad(QPointF(0, 0), bullet_size_c);
            radialGrad.setColorAt(0, Qt::white);
            radialGrad.setColorAt(1, Qt::yellow);
            QGraphicsItem *bullet = scene->addEllipse(0, 0, bullet_size_c, bullet_size_c, QPen(Qt::NoPen), QBrush(radialGrad));
            bullet->setPos(itemBat->pos().x() + bat_gen/2 - bullet_size_c/2, itemBat->pos().y() - bullet_size_c);
            this->bullets.push_back(bullet);
            this->bullets_fire_start_time = gameTime;
        }
    }

    // bat hareket
    if( mainWindow->isKeyDownLeft() ) {
        bat_has_target = false;
        bat_hand1->moveBy(-bat_hiz_x, 0);
        bat_hand2->moveBy(-bat_hiz_x, 0);
        itemBat->moveBy(-bat_hiz_x, 0);

        if( itemBat->pos().x() < 0 ) {
            itemBat->setPos(0, itemBat->pos().y());
            bat_hand1->setPos(0, bat_hand1->pos().y());
            bat_hand2->setPos((itemBat->pos().x() + bat_gen - 3), bat_hand2->pos().y());
        }
    }
    else if( mainWindow->isKeyDownRight() ) {
        bat_has_target = false;
        itemBat->moveBy(bat_hiz_x, 0);
        bat_hand1->moveBy(bat_hiz_x, 0);
        bat_hand2->moveBy(bat_hiz_x, 0);

        if( itemBat->pos().x() > scene->width() - bat_gen ) {
            itemBat->setPos(scene->width() - bat_gen, itemBat->pos().y());
            bat_hand1->setPos(itemBat->pos().x() , bat_hand1->pos().y());
            bat_hand2->setPos( (scene->width()-3) , bat_hand2->pos().y());
        }
    }
    else if( bat_has_target ) {
        int bat_centre_x = itemBat->pos().x() + bat_gen/2;
        int dist = abs(bat_centre_x - bat_target_x);
        if( dist <= bat_hiz_x ) {
            itemBat->setPos(bat_target_x - bat_gen/2, itemBat->pos().y());
            bat_has_target = false;
        }
        else {
            int dir = bat_target_x > bat_centre_x ? 1 : -1;
            itemBat->moveBy(dir * bat_hiz_x, 0);
        }
    }

    if( deleted_any_blocks ) {
        // check for level complete
        bool any_blocks = false;
        foreach(QGraphicsItem *item, scene->items()) {
            if( item->type() == CUSTOMITEMTYPE_BLOCK ) {
                BlockItem *blockItem = static_cast<BlockItem *>(item);
                if( blockItem->getBlockType() != BlockItem::BLOCKTYPE_BRICK ) {
                    any_blocks = true;
                    break;
                }
            }
        }
        if( !any_blocks ) {
            level_complete = true;
            this->setMessage("Level Completed!", true);
        }
    }
}


void PlayingGamestate::setMessage(const QString &text, bool message_pauses) {
    if( has_message ) {
        delete itemMessage;
    }
    has_message = true;
    this->message_pauses = message_pauses;
    itemMessage = scene->addText(text);
    QFont font = itemMessage->font();
    font.setPointSize(24);
    itemMessage->setFont(font);
    itemMessage->setPos((scene->width() - itemMessage->boundingRect().width())/2,     //ekran ortası(x)
                        (scene->height() - itemMessage->boundingRect().height())/2);  //ekran ortası(y)
    itemMessage->setDefaultTextColor(Qt::green);
    itemMessage->setZValue(1);
    message_start_time = gameTime;
}

bool PlayingGamestate::userQuit() {
    bool old_paused = paused;
    paused = true;
    if(QMessageBox::question(this->mainWindow, "QTronce", "Are you sure you wish to quit?", QDialogButtonBox::Ok, QDialogButtonBox::Cancel) == QDialogButtonBox::Ok);
    {
        OptionsGamestate *gamestate = new OptionsGamestate(mainWindow);
        mainWindow->setGamestate(gamestate);
        return true;
    }
    paused = old_paused;
    return false;
}

void PlayingGamestate::resizeEvent(QResizeEvent *event) {
    if( view != NULL ) {
        float scale_x = (view->width())  / (ekran_gen);
        float scale_y = (view->height()) / (ekran_uzun);
        float scale = qMin(scale_x, scale_y);
        view->scale(scale, scale);
    }
}

bool PlayingGamestate::hitBlock(BlockItem *blockItem) {
    this->changeScore(blockItem->getScore());
    switch(blockItem->getBlockType()){
    case BlockItem::BLOCKTYPE_EXTRALIFE:
        this->setMessage("Extra Life", false);
        this->changeLives(1);
        break;
    case BlockItem::BLOCKTYPE_FASTBALL:
        this->setMessage("FastBall!", false);
        ball_sp_x = ball_sp_x > 0 ? max_top_hiz_x : -max_top_hiz_x;
        break;
    case BlockItem::BLOCKTYPE_FIREBALL:
        this->setMessage("Fireball!", false);
        this->bonus_fireball = true;
        this->bonus_fireball_start_time = gameTime;
        setBallColor();
        break;
    case BlockItem::BLOCKTYPE_BULLETS:
        this->bonus_bullets = true;
        this->bonus_bullets_start_time = gameTime;
        this->bullets_fire_start_time = gameTime;
        break;

    default:
        break;
    }

    if(blockItem->getBlockType() != BlockItem::BLOCKTYPE_BRICK){
        blocks.removeOne(blockItem);
        QMutableHashIterator<int, BlockItem *> iter(blocksHashMap);
        if(iter.findNext(blockItem)){
            iter.remove();
        }
        delete blockItem;
        return true;
    }
    return false;
}

void PlayingGamestate::changeScore(int change) {
    const int life_every_c = 1000;
    int m1 = score / life_every_c;
    int m2 = (score+change) / life_every_c;
    score += change;
    itemScore->setPlainText("Score: " + QString::number(score));
    if( m1 != m2 ) {
        this->setMessage("Bonus Life!", false);
        this->changeLives(1);
    }
}

void PlayingGamestate::changeLives(int change) {
    lives += change;
    itemLives->setPlainText("Lives: " + QString::number(lives));
}

void PlayingGamestate::changeLevel(int change) {
    level += change;
    itemLevel->setPlainText("Level: " + QString::number(level));
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), gamestate(NULL), keydown_left(false), keydown_right(false) {
    QSettings settings;
    int size = settings.beginReadArray("hiscores");
    for(int i=0;i<size;i++) {
        settings.setArrayIndex(i);
        QString name = settings.value("name").toString();
        int score = settings.value("score").toInt();
        int level = settings.value("level").toInt();
        Hiscore hiscore(name, score, level);
        this->hiscores.push_back(hiscore);
    }
    settings.endArray();
    qStableSort(this->hiscores);
}

MainWindow::~MainWindow() {

}

void MainWindow::keyPressEvent(QKeyEvent *event) {
    if( event->key() == Qt::Key_Left ) {
        this->keydown_left = true;
    }
    else if( event->key() == Qt::Key_Right ) {
        this->keydown_right = true;
    }
    else if( event->key() == Qt::Key_Escape ) {
        gamestate->userQuit();
    }
    else if( event->key() == Qt::Key_P ) {
        gamestate->userPause();
    }
    else if (event->key() == Qt::Key_PageUp) {
        if(CHEAT)
            CHEAT = false;
        else
            CHEAT = true;
    }
    else {
        QMainWindow::keyPressEvent(event);
    }
}

void MainWindow::keyReleaseEvent(QKeyEvent *event) {
    if( event->key() == Qt::Key_Left ) {
        keydown_left = false;
    }
    else if( event->key() == Qt::Key_Right ) {
        keydown_right = false;
    }
    else {
        QMainWindow::keyReleaseEvent(event);
    }
}

void MainWindow::resizeEvent(QResizeEvent *event) {
    if( gamestate != NULL)
        gamestate->resizeEvent(event);
}

void MainWindow::updateScene() {
    if( qApp->activeWindow() == NULL )
        return;
    gamestate->updateScene();
}

void MainWindow::addHiscore(Hiscore hiscore) {
    this->hiscores.push_back(hiscore);
    qStableSort(this->hiscores);
    if( this->hiscores.size() > max_hiscore_sayisi ) {
//        en düşük skoru/skorları siler
        this->hiscores.erase(this->hiscores.begin() + max_hiscore_sayisi, this->hiscores.end());
    }
    this->saveHiscores();
}

void MainWindow::clearHiscores() {
    this->hiscores.clear();
    saveHiscores();
}

void MainWindow::saveHiscores() {
    QSettings settings;
    settings.beginWriteArray("hiscores");
    for(int i=0;i<hiscores.size();i++) {
        settings.setArrayIndex(i);
        settings.setValue("name", hiscores.at(i).getName());
        settings.setValue("score", hiscores.at(i).getScore());
        settings.setValue("level", hiscores.at(i).getLevel());
     }
    settings.endArray();
}
